﻿using System;
using System.Collections.Generic;

namespace DanMuHelper.Tools
{
    public class FsmSystem<T> where T : Enum
    {
        private Dictionary<T, IState<T>> _stateDic;
        private T _lastId;
        private T _currentStateId;
        private IState<T> _currentState;

        public T LastId => _lastId;

        public T Id => _currentStateId;

        public FsmSystem()
        {
            _stateDic = new Dictionary<T, IState<T>>();
        }

        public void Add(IState<T> state)
        {
            if (state == null) return;
            if (_stateDic.ContainsKey(state.Id)) return;

            _stateDic.Add(state.Id, state);
        }

        public State GetCurrentState<State>() where State : IState<T>
        {
            return (State)_currentState;
        }

        public State GetState<State>(T id) where State : IState<T>
        {
            return (State)_stateDic[id];
        }

        public void Remove(T id)
        {
            if (!_stateDic.ContainsKey(id)) return;

            _stateDic.Remove(id);
        }

        public bool Enter(T id)
        {
            if (!_stateDic.ContainsKey(id)) return false;

            _currentStateId = id;
            _lastId = id;
            _currentState = _stateDic[id];
            _currentState.OnEnterState();
            return true;
        }

        public void Update(float deltaTime)
        {
            if (_currentState == null) return;
            if (_currentState.TransitionState(deltaTime, out T id))
                TransferState(id);
            _currentState.OnUpdateState(deltaTime);
        }

        //转移状态函数
        private void TransferState(T id)
        {
            if (id.Equals(Id)) return;
            if (!_stateDic.ContainsKey(id)) return;

            _lastId = _currentStateId;
            _currentState.OnExitState();
            _currentState = _stateDic[id];
            _currentStateId = id;
            _currentState.OnEnterState();
        }

        //强制转移状态函数
        public void ForceTransferState(T id)
        {
            TransferState(id);
        }
    }
}